'use client'

import DeviceUpgrade from '@/components/device-upgrade'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Textarea } from '@/components/ui/textarea'
import { atom, useAtom, useAtomValue } from 'jotai'
import { atomWithStorage } from 'jotai/utils'
import React, { useEffect, useMemo, useState } from 'react'
import { DownloadIcon, MixerHorizontalIcon, ReloadIcon } from '@radix-ui/react-icons'
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover"
import { Checkbox } from '@/components/ui/checkbox'
import { produce } from "immer";
import { IoFilter } from "react-icons/io5";
import { Model, DeviceVersion } from '../model_version'
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'


function getRandomInt(min: number, max: number) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

type Response = {
  success: boolean,
  message: string,
  code: number,
  result: string,
  extraResult: string,
  timeStamp: number
}

type UpgradeDevice = {
  sn: string,
  url: string,
  response?: Response
}

enum Filter {
  unknown,
  success,
  fail
}

interface UpgradeConfig {
  md5: string
  size: string
  sns: string
  firmwareUrl: string
}

const upgradeConfigAtom = atomWithStorage<UpgradeConfig>("upgrade-config", { md5: "", size: "", sns: "", firmwareUrl: "" })

const canGenerateDevicesAtom = atom(
  (get) => {
    const config = get(upgradeConfigAtom);
    return config.md5 && config.size && config.sns && config.firmwareUrl
  }
)

const devicesAtom = atom<UpgradeDevice[]>([])
const upgradeResultFilterAtom = atom<Filter[]>([Filter.unknown, Filter.success, Filter.fail])

//filtered device, 
const filteredDevicesAtom = atom((get) => {
  const devices = get(devicesAtom)
  const filter = get(upgradeResultFilterAtom)
  return devices.filter((x) => {
    return (filter.includes(Filter.unknown) && !x.response)
      || (filter.includes(Filter.success) && x.response?.success === true)
      || (filter.includes(Filter.fail) && x.response?.success === false)

  })
})

const deviceVersionAtom = atom(DeviceVersion.China)


function BatchUpgrade() {
  const [upgradeConfig, setUpgradeConfig] = useAtom(upgradeConfigAtom)
  const canGenerateDevices = useAtomValue(canGenerateDevicesAtom)
  const [upgradingAllDevices, setUpgradingAllDevices] = useState(false)
  const [devices, setDevices] = useAtom(devicesAtom)
  const [upgradeResultFilter, setUpgradeResultFilter] = useAtom(upgradeResultFilterAtom)
  const filteredDevices = useAtomValue(filteredDevicesAtom)
  const [deviceVersion, setDeviceVersion] = useAtom(deviceVersionAtom)

  const sums = useMemo(() => {
    const result: number[] = new Array(Object.values(Filter).length / 2).fill(0);
    for (const dev of devices) {
      if (dev.response) {
        if (dev.response.success) {
          result[Filter.success] += 1
        } else {
          result[Filter.fail] += 1
        }
      } else {
        result[Filter.unknown] += 1
      }
    }
    return result
  }, [devices])


  async function upgrade(sn: string) {
    const device = devices.find((x) => x.sn === sn);
    console.log(device?.url);
    const resp = await fetch(device!.url);
    const response = await resp.json() as Response;

    setDevices(d => {
      const nextState = produce(d, draft => {
        const index = draft.findIndex(x => x.sn === sn)
        draft[index].response = response
      })
      return nextState
    })
  }

  function resetUpgradeState(sn?: string) {
    setDevices(dvs => produce(dvs, draft => {
      if (sn) {
        const index = draft.findIndex(x => x.sn === sn)
        delete draft[index].response
      } else {
        draft.forEach(x => delete x.response)
      }
    }))
  }

  async function upgradeAllDevices() {
    resetUpgradeState()
    setUpgradingAllDevices(true)
    try {
      for (const device of devices) {
        await upgrade(device.sn)
        await new Promise(resolve => setTimeout(resolve, 125))
      }
    } catch (error) {
      alert(error)
    } finally {
      setUpgradingAllDevices(false)
    }
  }

  function generateUpgradeDevices() {
    const lines = upgradeConfig.sns.split(/[,|\n]/).map((x) => x.trim()).filter((x) => !!x);
    const devices = lines.map((sn) => {
      const encodedDownloadUri = encodeURIComponent(upgradeConfig.firmwareUrl);
      const url = `https://api.pick-fun.com${deviceVersion === DeviceVersion.China ? ".cn" : ""}/app/common/deviceForceUpgradeUrl?md5=${upgradeConfig.md5}&size=${upgradeConfig.size}&sn=${sn}&url=${encodedDownloadUri}`;
      return {
        sn: sn,
        url: url,

      }
    });
    setUpgradeResultFilter([Filter.unknown, Filter.success, Filter.fail])
    setDevices(devices)
  }





  const updateConfig = (prop: keyof UpgradeConfig, value: string) => {
    const nextState = produce(upgradeConfig, draft => {
      draft[prop] = value
    });
    setUpgradeConfig(nextState)
  }


  return (
    <div className='flex flex-col md:flex-row p-4 gap-x-4'>
      <div className='flex flex-col flex-1 gap-y-4'>
        <div>
          <Label className=''>固件MD5值</Label>
          <Input value={upgradeConfig.md5} onChange={(e) => updateConfig("md5", e.target.value.trim())} />
        </div>
        <div>
          <Label className=''>固件大小</Label>
          <Input value={upgradeConfig.size} onChange={(e) => updateConfig('size', e.target.value.trim())} />
        </div>

        <div className=''>
          <Label className='flex-row flex items-center mb-1'>
            固件下载链接
            <a href={upgradeConfig.firmwareUrl} className='flex-row flex items-center ml-2 hover:no-underline' target='_blank'>
              <DownloadIcon className="h-4 w-4" />测试下载
            </a>
          </Label>
          <Textarea value={upgradeConfig.firmwareUrl} onChange={(e) => updateConfig("firmwareUrl", e.target.value.trim())} />
        </div>

        <div>
          <Label className=''>设备SN(多个序列号以回车或逗号分隔)</Label>
          <Textarea rows={10} value={upgradeConfig.sns} onChange={(e) => updateConfig("sns", e.target.value)} />
        </div>
        <div className="flex flex-row items-center gap-x-4">
          <Button disabled={!canGenerateDevices} onClick={generateUpgradeDevices}>生成升级链接</Button>
          <RadioGroup
            value={deviceVersion}
            onValueChange={(value) => {
              setDeviceVersion(value as DeviceVersion)
            }}
            defaultValue={deviceVersion}>
            <div className="flex items-center space-x-2">
              <RadioGroupItem value={DeviceVersion.Oversea} id="v1" />
              <Label htmlFor="v1">海外版</Label>
            </div>
            <div className="flex items-center space-x-2">
              <RadioGroupItem value={DeviceVersion.China} id="v2" />
              <Label htmlFor="v2">国内版</Label>
            </div>
          </RadioGroup>
        </div>
      </div>
      {devices.length > 0 &&
        <div className='flex flex-col flex-1 gap-y-2'>
          <div className='flex flex-row gap-x-2'>
            <Button
              className='mt-4 self-start'
              variant={'outline'}
              disabled={upgradingAllDevices}
              onClick={upgradeAllDevices}>
              {upgradingAllDevices && <ReloadIcon className="mr-2 h-4 w-4 animate-spin" />}
              {upgradingAllDevices ? '升级中...' : `全部升级(${devices.length})`}
            </Button>
            <Popover>
              <PopoverTrigger asChild>
                <Button className='mt-4 self-start' variant='outline' size='icon'>
                  <IoFilter className="h-4 w-4" />
                </Button>
              </PopoverTrigger>
              <PopoverContent className="w-32 flex flex-col gap-y-2">
                {
                  Object.values(Filter).filter(x => typeof x === 'number').map((filter) =>
                    <div className="flex items-center space-x-2" key={filter}>
                      <Checkbox id={`filter-${filter}`} value={filter} checked={upgradeResultFilter.includes(filter)}
                        onCheckedChange={(checked: boolean) => {
                          const result = checked ? [...upgradeResultFilter, filter] : upgradeResultFilter.filter(x => x !== filter)
                          return setUpgradeResultFilter(result)
                        }} />
                      <label
                        htmlFor={`filter-${filter}`}
                        className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
                      >
                        {filter === Filter.unknown ? `未知 (${sums[filter]})` : filter === Filter.success ? `成功 (${sums[filter]})` : `失败 (${sums[filter]})`}
                      </label>
                    </div>
                  )
                }
              </PopoverContent>
            </Popover>
          </div>
          {filteredDevices.map((device) =>
            <DeviceUpgrade key={device.sn} {...device} {...device.response} upgradeClicked={(sn) => { resetUpgradeState(sn); upgrade(sn); }} />
          )}
        </div>}
    </div>
  )
}

export default BatchUpgrade